package com.westdream.config;

import java.io.IOException;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;

import javax.servlet.ServletContext;

import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.xpath.XPath;

public class Configuration implements Serializable, ConfigConstant {

	private static final long serialVersionUID = -8572272649468107517L;
	
	private static Configuration config = null;
	private HashMap<String, ActionConfig> actionMappings = new HashMap<String, ActionConfig>();
	private HashMap<String, FormConfig> formMappings = new HashMap<String, FormConfig>();
	
	public HashMap<String, FormConfig> getFormMappings() {
		return formMappings;
	}

	private Configuration() {

	}

	public static Configuration newInstance() {
		if (null == config) {
			config = new Configuration();
		}
		return config;
	}
	
	public Configuration configure(final ServletContext context) {
		return configure(DEFAULT_CONFIG_FILE, context);
	}

	@SuppressWarnings("unchecked")
	public Configuration configure(final String cfg , final ServletContext context)
			throws ConfigurationException {
		if (null == cfg | "".equals(cfg.trim()))
			throw new ConfigurationException("Configuration file is required.");
		/** 使用JDOM的SAX解析配置文件 **/
		SAXBuilder saxBuilder = new SAXBuilder();
		try {
			Document document = saxBuilder.build(Thread.currentThread()
					.getContextClassLoader().getResourceAsStream(cfg));
			Element root = document.getRootElement();
			List<Element> actionElmts = (List<Element>)XPath.selectNodes(root, VIEW_ACTION);
			for(Element actionElmt : actionElmts) {
				ActionConfig actionConfig = new ActionConfig();
				/** 将配置文件的Action属性装配到ActionConfig **/
				actionConfig.setPath(context.getContextPath() + actionElmt.getAttributeValue(ACTION_ATTRIB_PATH));
				actionConfig.setClassName(actionElmt.getAttributeValue(ACTION_ATTRIB_CLASS));
				actionConfig.setName(actionElmt.getAttributeValue(ACTION_ATTRIB_NAME));
				
				/** 将配置文件的Action的result子节点装配到ActionConfig **/
				List<Element> resultElmts = actionElmt.getChildren(ACTION_CHILDREN_RESULT);
				for(Element resultElmt : resultElmts) {
					ResultConfig resultConfig = new ResultConfig();
					Attribute nameAttrib = resultElmt.getAttribute(ACTION_CHILDREN_RESULT_NAME);
					Attribute pathAttrib = resultElmt.getAttribute(ACTION_CHILDREN_RESULT_PATH);
					Attribute typeAttrib = resultElmt.getAttribute(ACTION_CHILDREN_RESULT_TYPE);
					resultConfig.setName(nameAttrib.getValue());
					resultConfig.setForward(typeAttrib.getBooleanValue());
					resultConfig.setPath(pathAttrib.getValue());			
					actionConfig.getResults().put(resultConfig.getName(), resultConfig);
				}
				/** 将ActionConfig装配到Configuration **/
				actionMappings.put(actionConfig.getPath(), actionConfig);
			}
			
			/** 将配置文件的form属性装配到FormConfig **/
			List<Element> formElmts = (List<Element>)XPath.selectNodes(root, VIEW_FORMS_FORM);
			for(Element formElmt : formElmts) {
				FormConfig formConfig = new FormConfig();
				formConfig.setName(formElmt.getAttributeValue(FORM_ATTRIB_NAME));
				formConfig.setClassName(formElmt.getAttributeValue(FORM_ATTRIB_CLASS));
				
				List<Element> propertyElmts = formElmt.getChildren(FORM_CHILDREN_PROP);
				for(Element propertyElmt : propertyElmts) {
					PropertyConfig propertyConfig = new PropertyConfig();
					propertyConfig.setName(propertyElmt.getAttributeValue(FORM_CHILDREN_PROP_NAME));
					propertyConfig.setType(propertyElmt.getAttributeValue(FORM_CHILDREN_PROP_TYPE));
					propertyConfig.setValue(propertyElmt.getAttributeValue(FORM_CHILDREN_PROP_VALUE));
					formConfig.getProperties().add(propertyConfig);
				}
				formMappings.put(formConfig.getName(), formConfig);
			}
			
			
		} catch (JDOMException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return config;
	}
	
	public HashMap<String, ActionConfig> getActionMappings() {
		return actionMappings;
	}

}
